package com.ruoyi.visitor.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.mail.EmailUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysNoticeMapper;
import com.ruoyi.system.mapper.SysPostMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.visitor.config.VisitorConst;
import com.ruoyi.visitor.domain.VisitorAppointment;
import com.ruoyi.visitor.domain.VisitorAppointmentStaff;
import com.ruoyi.visitor.domain.VisitorCodeCheck;
import com.ruoyi.visitor.domain.VisitorWxUser;
import com.ruoyi.visitor.mapper.VisitorAppointmentMapper;
import com.ruoyi.visitor.mapper.VisitorAppointmentStaffMapper;
import com.ruoyi.visitor.mapper.VisitorCodeCheckMapper;
import com.ruoyi.visitor.mapper.VisitorWxUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.TimerTask;

/**
 * packageName com.ruoyi.visitor.service.impl
 *
 * @author wfx
 * @version JDK 8
 * @className VisitorAppService
 * @date 2025/4/22
 * @description TODO
 */
@Service
public class VisitorAppService {
    @Autowired
    private VisitorWxUserMapper wxUserMapper;
    @Autowired
    private VisitorAppointmentMapper visitorAppointmentMapper;
    @Autowired
    private VisitorCodeCheckMapper codeCheckMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    public SysNoticeMapper sysNoticeMapper;
    @Autowired
    public SysDeptMapper deptMapper;
    @Autowired
    public SysUserMapper userMapper;
    @Autowired
    public SysPostMapper postMapper;
    @Autowired
    private VisitorAppointmentStaffMapper visitorAppointmentStaffMapper;
    /**
     * 微信登录
     * 1. 访客用户 直接登录
     * 2. 员工&门卫
     *      2.1 验证sys_user 表手机号是否存在
     *          2.1.1 不存在 登录失败
     *      2.2 验证 wx_user 表是否存在记录
     *          2.2.1 不存在 插入数据
     *          2.2.2 已存在
     *              验证wx_user   phone是否存在，不存在 则更新
     *              验证wx_user   phone是否存在，存在  openid&&phone 是否一致; 一致则更新
     * @param visitorWxUser
     * @return
     */
    public Integer wxLogin(VisitorWxUser visitorWxUser){
        String openid = visitorWxUser.getOpenid();
        String phone = visitorWxUser.getPhonenumber();
        String userType = visitorWxUser.getWxUserType();
        //1. 访客用户
        VisitorWxUser wxUser = wxUserMapper.selectVisitorWxUserByOpenid(openid);
        if(Objects.equals(VisitorConst.WX_USER_TYPE_V,userType)){
            if(Objects.isNull(wxUser)){
                visitorWxUser.setId(IdUtil.getSnowflake().nextId());
                visitorWxUser.setCreateTime(DateTime.now());
                return wxUserMapper.insertVisitorWxUser(visitorWxUser);
            }else{
                wxUser.setWxUserType(userType);
                wxUser.setLastLoginTime(DateTime.now());
                return wxUserMapper.updateVisitorWxUser(wxUser);
            }
        }
        //2. 员工&门卫
        if(!PhoneUtil.isMobile(phone)){
            throw new ServiceException("手机号码不正确");
        }
        //2. 员工 && 门卫
        SysUser user = sysUserMapper.selectUserByPhoneNumber(phone);
        //2. 门卫岗登录方式只能是D
        List<SysPost> postList = postMapper.selectPostsByUserId(user.getUserId());
        for(SysPost post: postList){
            if(Objects.equals(VisitorConst.DOOR_POST,post.getPostCode())){
                if(!Objects.equals(VisitorConst.WX_USER_TYPE_D,userType)){
                    throw new ServiceException("您没有权限登录");
                }
            }
        }
        if(Objects.equals(VisitorConst.WX_USER_TYPE_D,userType) ||
                Objects.equals(VisitorConst.WX_USER_TYPE_E,userType) ) {
            //2.1 验证员工表手机号码
            if(Objects.isNull(user)){
                throw new ServiceException("手机号码不存在");
            }
        }
        //2.2 验证 wx_user 表是否存在记录
        if(!Objects.isNull(wxUser)){
            //wx_user表手机号存在 则验证是否一致
            if(StringUtils.isNotBlank(wxUser.getPhonenumber())
                    &&!Objects.equals(phone,wxUser.getPhonenumber())){
                throw new ServiceException("手机号码不正确");
            }else{
                wxUser.setPhonenumber(phone);
            }
        }
        if(Objects.isNull(wxUser)){
            //判定手机号是否已经被占用, 如果已被占用,则无法登录
            VisitorWxUser exists = wxUserMapper.selectVisitorWxUserByPhonenumber(phone);
            if(!Objects.isNull(exists)){
                throw new ServiceException("手机号码已注册");
            }
            visitorWxUser.setId(IdUtil.getSnowflake().nextId());
            visitorWxUser.setCreateTime(DateTime.now());
            return wxUserMapper.insertVisitorWxUser(visitorWxUser);
        }else{
            wxUser.setLastLoginTime(DateTime.now());
            wxUser.setWxUserType(visitorWxUser.getWxUserType());
            return wxUserMapper.updateVisitorWxUser(wxUser);
        }
    }

    /**
     * 插入预约申请
     * @param visitorAppointment
     * @return
     */
    public int insertVisitorAppointment(VisitorAppointment visitorAppointment)
    {
        if(!IdcardUtil.isValidCard(visitorAppointment.getVisitorIdcard())){
            throw new ServiceException("访客身份证号不正确");
        }
        if(!PhoneUtil.isMobile(visitorAppointment.getVisitorPhone())){
            throw new ServiceException("访客手机号码正确");
        }
        String visitedDept = visitorAppointment.getVisitedDept();
        SysDept dept = new SysDept();
        dept.setDeptName(visitedDept);
        List<SysDept> list = deptMapper.selectDeptList(dept);
        if(!Objects.isNull(list) && !list.isEmpty()){
            dept = list.get(0);
        }
        String leader = dept.getLeader();
        SysUser user = new SysUser();
        user.setUserName(leader);
        List<SysUser> userList = userMapper.selectUserList(user);
        if(!Objects.isNull(userList) && !userList.isEmpty()){
            user = userList.get(0);
        }else{
            throw new ServiceException("部门负责人未找到");
        }
        String visitedPhone = user.getPhonenumber();
        if(!PhoneUtil.isMobile(visitedPhone)){
            throw new ServiceException("被访问人手机号码不正确");
        }
        visitorAppointment.setVisitedPhone(visitedPhone);
        visitorAppointment.setVisitedName(leader);
        visitorAppointment.setId(IdUtil.getSnowflake().nextId());
        visitorAppointment.setAppointmentTime(DateTime.now());
        visitorAppointment.setCreateTime(DateUtils.getNowDate());
        visitorAppointment.setApprovalStatus(VisitorConst.APPROVALSTATUS_P);
        List<VisitorAppointmentStaff> staffList = visitorAppointment.getStaffList();
        if(!Objects.isNull(staffList) && !staffList.isEmpty()){
            staffList.stream().forEach(staff->{
                staff.setId(IdUtil.getSnowflake().nextId());
                staff.setAppointmentId(visitorAppointment.getId());
                staff.setCreateTime(DateUtils.getNowDate());
                visitorAppointmentStaffMapper.insertVisitorAppointmentStaff(staff);
            });
        }
        visitorAppointmentMapper.insertVisitorAppointment(visitorAppointment);
        //发送邮寄通知
        String to = user.getEmail();
        if(StringUtils.isNotBlank(to)) {
            String subject = "访客预约提醒";
            String content = visitorAppointment.getVisitorName();
            content = content + DateUtil.format(visitorAppointment.getEta(), DateUtils.YYYY_MM_DD_HH_MM);
            content = content + " 预约:" + visitorAppointment.getReason()+";请尽快审批。";
            final String mailContent = content;
            AsyncManager.me().execute(new TimerTask() {
                @Override
                public void run() {
                    EmailUtils.sendEmail163(to, subject, mailContent);
                }
            });
        }
        return 1;
    }

    /**
     * 预约审核
     * @return
     */
    public Integer visitorApproval(Long appointmentId, String approvalStatus){
        VisitorAppointment appointment = new VisitorAppointment();
        appointment.setId(appointmentId);
        appointment.setApprovalStatus(approvalStatus);
        appointment.setUpdateTime(DateTime.now());
        if(Objects.equals(VisitorConst.APPROVALSTATUS_A,approvalStatus)){
            appointment.setEnterCode(RandomUtil.randomNumbers(6));
            appointment.setLeaveCode(RandomUtil.randomNumbers(6));
        }
        return visitorAppointmentMapper.updateVisitorAppointment(appointment);
    }

    /**
     * 查询我的预约
     * @param openid
     * @return
     */
    public List<VisitorAppointment> selectMyVisitorAppointmentList(String openid)
    {
        VisitorAppointment visitorAppointment = new VisitorAppointment();
        visitorAppointment.setOpenid(openid);
        return visitorAppointmentMapper.selectVisitorAppointmentList(visitorAppointment);
    }

    /**
     * 查询我的审核
     * @param visitorAppointment
     * @return
     */
    public List<VisitorAppointment> selectMyApprovalList(String openid,VisitorAppointment visitorAppointment)
    {
        VisitorWxUser wxUser = wxUserMapper.selectVisitorWxUserByOpenid(openid);
        //查询条件
        VisitorAppointment appointment = new VisitorAppointment();
        appointment.setVisitedPhone(wxUser.getPhonenumber());
        return visitorAppointmentMapper.selectVisitorAppointmentList(appointment);
    }

    public VisitorAppointment selectVisitorAppointmentById(Long id)
    {
        VisitorAppointment appointment = visitorAppointmentMapper.selectVisitorAppointmentById(id);
        VisitorAppointmentStaff staff = new VisitorAppointmentStaff();
        staff.setAppointmentId(id);
        List<VisitorAppointmentStaff> staffList = visitorAppointmentStaffMapper.selectVisitorAppointmentStaffList(staff);
        appointment.setStaffList(staffList);
        appointment.setEtd(DateUtils.addDays(appointment.getEta(),appointment.visitedDays));
        return appointment;
    }
    /**
     * 访客码核验
     * @param code
     * @param openid 核验人
     */
    public void checkvisitorCode(String code,String openid){
        /**
         * 1. 判断访客码是否正确(存在 且 当天  且  正确)
         * 2. 判断是否已经核验
         * 3. 判断按先进后出顺序->必须是进入码 或 已经有进入的的离开吗
         */
        // 1. 判断访客码是否正确(存在 且 正确)
        String day = DateUtil.today();
        VisitorAppointment appointment = visitorAppointmentMapper.selectVisitorAppointment(code,day);
        if(Objects.isNull(appointment)){
            throw new ServiceException("访客码不正确");
        }
        Long appointmentId = appointment.getId();
        // 2. 判断是否已经核验
        VisitorCodeCheck codeCheck = new VisitorCodeCheck();
        codeCheck.setAppointmentId(appointmentId);
        codeCheck.setCheckCode(code);
        List<VisitorCodeCheck> codeCheckList = codeCheckMapper.selectVisitorCodeCheckList(codeCheck);
        if(!Objects.isNull(codeCheckList) && codeCheckList.size()>0){
            throw new ServiceException("访客码已过期");
        }
        /**
         * 3. 判断按先进后出顺序->必须是进入码 或 已经有进入的的离开吗
         *    如果是离开码 && 没有进入码核验记录->报错。
          */
        if(Objects.equals(code,appointment.getLeaveCode())){
            String enterCode = appointment.getEnterCode();
            VisitorCodeCheck enterCodeCheck = new VisitorCodeCheck();
            enterCodeCheck.setAppointmentId(appointmentId);
            enterCodeCheck.setCheckCode(enterCode);
            enterCodeCheck.setCheckType(VisitorConst.CHECKTYPE_E);
            List list = codeCheckMapper.selectVisitorCodeCheckList(enterCodeCheck);
            if(Objects.isNull(list) || list.isEmpty()){
                throw new ServiceException("访客码无进入记录");
            }
        }
        if(Objects.equals(code,appointment.getEnterCode())){
            codeCheck.setCheckType(VisitorConst.CHECKTYPE_E);
        }else{
            codeCheck.setCheckType(VisitorConst.CHECKTYPE_L);
        }
        codeCheck.setId(IdUtil.getSnowflake().nextId());
        codeCheck.setCheckCode(code);
        codeCheck.setAppointmentId(appointmentId);
        codeCheck.setCheckTime(DateTime.now());
        codeCheck.setOpenid(openid);
        codeCheck.setVisitorIdcard(appointment.getVisitorIdcard());
        codeCheck.setVisitorName(appointment.getVisitorName());
        codeCheck.setCreateTime(DateTime.now());
        codeCheckMapper.insertVisitorCodeCheck(codeCheck);
    }

}